package net.daum.mail;

import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.lang.StringUtils;
import org.apache.james.mime4j.MimeException;
import org.apache.james.mime4j.MimeIOException;
import org.apache.james.mime4j.codec.DecoderUtil;
import org.apache.james.mime4j.dom.Entity;
import org.apache.james.mime4j.dom.Message;
import org.apache.james.mime4j.dom.Multipart;
import org.apache.james.mime4j.dom.TextBody;
import org.apache.james.mime4j.dom.field.ContentDispositionField;
import org.apache.james.mime4j.message.DefaultMessageBuilder;

public class FileMimeRenderer {

	private static final String MULTIPART_RELATIVE_SUBTYPE = "relative";
	private static final String MULTIPART_ALTERNATIVE_SUBTYPE = "alternative";
	private static final String MULTIPART_MIXED_SUBTYPE = "mixed";

	Message message;
	String text = new String();
	List<Object> attachments = new ArrayList<Object>();

	public FileMimeRenderer(String filename) throws IOException, MimeException {
		DefaultMessageBuilder builder = new DefaultMessageBuilder();
		message = builder.parseMessage(new FileInputStream(filename));
		parseMessage(message);
	}
	
	public FileMimeRenderer(InputStream inputStream) throws MimeIOException, IOException {
		DefaultMessageBuilder builder = new DefaultMessageBuilder();
		message = builder.parseMessage(inputStream);
		parseMessage(message);
	}

	private void parseMessage(Message message) {
		System.out.println("parse message");
		parseEntity(message);
	}

	private void parseEntity(Entity entity) {
		System.out.println("Entity mimetype : " + entity.getMimeType());
		if (canRender(entity) && !StringUtils.equals(entity.getDispositionType(), ContentDispositionField.DISPOSITION_TYPE_ATTACHMENT)) {
			if (entity.isMultipart()) {
				parseMultipart(entity);
			} else if (canRender(entity)) {
				parseTextBody(entity);
			}	
		} else {
			parseAttachment(entity);
		}
	}

	private void parseMultipart(Entity entity) {

		Multipart multipart = (Multipart) entity.getBody();
		System.out.println("multipart.getSubType() : " + multipart.getSubType());

		if (StringUtils.equals(MULTIPART_MIXED_SUBTYPE, multipart.getSubType())) {
			parseMultipartMixed(multipart);
		} else if (StringUtils.equals(MULTIPART_ALTERNATIVE_SUBTYPE,
				multipart.getSubType())) {
			parseMultipartAlternative(multipart);
		} else if (StringUtils.equals(MULTIPART_RELATIVE_SUBTYPE,
				multipart.getSubType())) {
			parseMultipartRelative(multipart);
		}
	}

	private void parseMultipartAlternative(Multipart multipart) {
		Entity renderEntity = null;
		for (Entity part : multipart.getBodyParts()) {
			if (canRender(part)) {
				renderEntity = part;
			}
		}
		parseEntity(renderEntity);
	}

	private boolean canRender(Entity part) {
		// TODO Auto-generated method stub
		return true;
	}

	private void parseMultipartRelative(Multipart multipart) {
		parseMultipartMixed(multipart);
		matchRelatedContentId();
	}

	private void matchRelatedContentId() {
		// TODO Auto-generated method stub
	}

	private void parseMultipartMixed(Multipart multipart) {
		for (Entity part : multipart.getBodyParts()) {
			parseEntity(part);
		}
	}

	private void parseAttachment(Entity entity) {
		System.out.println("parse Attachment : " + entity.getMimeType());
		System.out.println("Filename : " + DecoderUtil.decodeEncodedWords(entity.getFilename(), null));
		System.out.println("disposition : " + entity.getDispositionType());
		attachments.add(entity);
		// BinaryBody body = (BinaryBody) entity.getBody();
	}

	private void parseTextBody(Entity entity) {
		System.out.println("parse TextBody");
		try {
			TextBody body = (TextBody) entity.getBody();
			ByteArrayOutputStream baos = new ByteArrayOutputStream();
			body.writeTo(baos);
			text = text + new String(baos.toByteArray(), body.getMimeCharset());
		} catch (Exception e) {
			/* ignore */
		}
	}

	public List<Object> getAttachments() {
		return attachments;
	}
	
	public String getText() {
		return text;
	}

	public Message getMessage() {
		return message;
	}

}
